#ifndef CRC_H
#define CRC_H


#include <string>
#include <sstream>
#include <vector>
#include "digest.h"


//________________________________________________________________________________________

//	crc_hash


//		Overloaded hash functions


//________________________________________________________________________________________

bool init_crc_hash();
extern t_digest* CrcXor;
#define HINIT1	0xFAC432B1UL
#define HINIT2	0x0CD5E44AUL

inline t_digest& crc_hash(const char *p, t_digest& hv)
{
	static bool initialize = init_crc_hash();
	initialize++;
	hv.digest[0] = HINIT1;
	hv.digest[1] = HINIT2;

	while (*p)
	{
		int i = (hv.digest[0] >> 24) & 0xff;
		hv.digest[0] = (hv.digest[0] << 8) ^ (int)(hv.digest[1] >> 24) ^ CrcXor[i].digest[0];
		hv.digest[1] = (hv.digest[1] << 8) ^ *p ^ CrcXor[i].digest[1];
		++p;
	}
	return(hv);
}
inline t_digest& crc_hash(const std::string& s, t_digest& hv)
{
	static bool initialize = init_crc_hash();
	initialize++;
	hv.digest[0] = HINIT1;
	hv.digest[1] = HINIT2;

	std::string::const_iterator end	= s.end();
	std::string::const_iterator p	= s.begin();
	while (p != end)
	{
		int i = (hv.digest[0] >> 24) & 0xff;
		hv.digest[0] = (hv.digest[0] << 8) ^ (int)(hv.digest[1] >> 24) ^ CrcXor[i].digest[0];
		hv.digest[1] = (hv.digest[1] << 8) ^ *p ^ CrcXor[i].digest[1];
		++p;
	}
	return(hv);
}

inline t_digest& crc_hash(std::string::const_iterator p,
							const std::string::const_iterator& end, t_digest& hv)
{
	static bool initialize = init_crc_hash();
	initialize++;
	hv.digest[0] = HINIT1;
	hv.digest[1] = HINIT2;

	while (p != end)
	{
		int i = (hv.digest[0] >> 24) & 0xff;
		hv.digest[0] = (hv.digest[0] << 8) ^ (int)(hv.digest[1] >> 24) ^ CrcXor[i].digest[0];
		hv.digest[1] = (hv.digest[1] << 8) ^ *p ^ CrcXor[i].digest[1];
		++p;
	}
	return(hv);
}

inline t_digest& crc_hash(const std::vector<std::string> lines, t_digest& hv)
{
	static bool initialize = init_crc_hash();
	initialize++;
	hv.digest[0] = HINIT1;
	hv.digest[1] = HINIT2;

	for (unsigned i = 0; i < lines.size(); ++i)
	{
		std::string::const_iterator end	= lines[i].end();
		std::string::const_iterator p	= lines[i].begin();
		for (; p != end; ++p)
		{
			int i = (hv.digest[0] >> 24) & 0xFF;
			hv.digest[0] = (hv.digest[0] << 8) ^ (int)(hv.digest[1] >> 24) ^ CrcXor[i].digest[0];
			hv.digest[1] = (hv.digest[1] << 8) ^ *p ^ CrcXor[i].digest[1];
		}
	}
	return(hv);
}

#endif

